/*
 * Time : 2022/12/9 18:14
 * Auth : weixinlong
 * Email : weixinlong@buaa.edu.cn
 * File : label.go
 */

package model

import (
	"errors"
	"fmt"

	"gorm.io/gorm"

	"hertz/demo/biz/util"
)

func AddLabel(db *gorm.DB, value *Label) error {
	if value.Status == "" {
		value.Status = LABEL_WORKING
	}

	if value.Status == LABEL_CONFIRM {
		return db.Transaction(func(tx *gorm.DB) error {
			var maybe Label
			err := tx.Where("media_id = ? AND status = ?", value.MediaID, SELECTION_CONFIRM).Take(&maybe).Error
			if err == nil {
				return fmt.Errorf("can't create second confirmed label")
			}
			if !errors.Is(err, gorm.ErrRecordNotFound) {
				return err
			} else {
				return tx.Create(value).Error
			}
		})

	} else {
		return db.Create(value).Error
	}
}

func DeleteLabel(db *gorm.DB, id uint, isAdmin bool, authorId uint) error {
	var origin Label
	origin.ID = id
	if err := db.Take(&origin).Error; err != nil {
		return err
	}
	if !isAdmin && origin.AuthorID != authorId {
		return fmt.Errorf("normal user can only modify your own label")
	}
	return db.Delete(&Label{}, id).Error
}

func UpdateLabelStatus(db *gorm.DB, id uint, status string, isAdmin bool, authorId uint) error {
	if !IsValidLabelStatus(status) {
		return fmt.Errorf("invalid status: %s", status)
	}

	if status == LABEL_CONFIRM {
		err := db.Transaction(func(tx *gorm.DB) error {
			var origin Label
			origin.ID = id
			if err := tx.Take(&origin).Error; err != nil {
				return err
			}
			mediaID := origin.MediaID
			if origin.Status == LABEL_CONFIRM && !isAdmin {
				return util.CanRetError(fmt.Errorf("only admin can change confirm state"))
			}

			err := tx.Model(Label{}).Where("status = ? AND media_id = ?", LABEL_CONFIRM, mediaID).Update("status", LABEL_WORKING).Error
			if err != nil {
				return err
			}
			return tx.Model(&origin).Update("status", SELECTION_CONFIRM).Error
		})
		return err
	} else {
		if !isAdmin {
			// 非管理员只能修改自己的标注
			var origin Label
			origin.ID = id
			if err := db.Take(&origin).Error; err != nil {
				return err
			}
			if origin.AuthorID != authorId {
				return fmt.Errorf("normal user can only modify your own label")
			}
		}

		return db.Model(&Label{ID: id}).Update("status", status).Error
	}
}

func UpdateLabel(db *gorm.DB, value *Label, isAdmin bool, authorId uint) error {
	// 不能更新状态
	value.Status = ""

	return db.Transaction(func(tx *gorm.DB) error {
		var origin Label
		origin.ID = value.ID
		if err := tx.Take(&origin).Error; err != nil {
			return err
		}

		if origin.Status == LABEL_CONFIRM {
			return util.CanRetError(fmt.Errorf("can't update confirmed label"))
		}
		if !isAdmin && origin.AuthorID != authorId {
			return fmt.Errorf("normal user can only modify your own label")
		}

		return tx.Updates(value).Error
	})
}

func GetLabelByID(db *gorm.DB, id uint) (*Label, error) {
	ret := Label{}
	ret.ID = id
	if err := db.Take(&ret).Error; err != nil {
		return nil, err
	}
	return &ret, nil
}

func UpdateLabelComment(db *gorm.DB, id uint, comment string, isAdmin bool, authorId uint) error {
	return db.Transaction(func(tx *gorm.DB) error {
		var origin Label
		origin.ID = id
		if err := tx.Take(&origin).Error; err != nil {
			return err
		}

		if origin.Status == LABEL_CONFIRM {
			return util.CanRetError(fmt.Errorf("can't update confirmed label"))
		}
		if !isAdmin && origin.AuthorID != authorId {
			return fmt.Errorf("normal user can only modify your own label")
		}

		return tx.Model(&Label{ID: id}).Update("comment", comment).Error
	})
}
